#include "RecordFile.hpp"
#include <stdexcept>
#include <cstring>

void RecordFile::Start(BaseFormat* saveFormat,const std::filesystem::path& savepath,const BaseFormatAdditionalInf& Additional)
{
  format=saveFormat;
  if(workthread.joinable())
    throw std::logic_error("RecordFile still working");
  format->Start(savepath,Additional);
  workthread=std::jthread([this](std::stop_token token){
    ImageType img;
    while(!token.stop_requested() && saveQueue.ConsumeSync(img))
    {
      auto currentTime=std::chrono::steady_clock::now();
      format->FileSaveFuncCall(img);
      delete [] img.data;
      FileSaveTime=std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now()-currentTime).count();
    }
    while(saveQueue.Consume(img))
    {
      format->FileSaveFuncCall(img);
      delete [] img.data;
    }
  });
}

void RecordFile::Stop()
{
  if(!workthread.joinable())
    throw std::logic_error("RecordFile not work,can't stop");
  workthread.request_stop();
  saveQueue.Finish();
  workthread.join();
  format->Stop();
  delete format;
}

void RecordFile::operator<<(const ImageType data)
{
  queueSize=saveQueue.Size();
  if(queueSize>=QUEUE_MAXSIZE)
    throw std::runtime_error("the queue full");
  unsigned char* newdata=new unsigned char[data.size];
  memcpy(newdata,(char*)data.data,data.size);
  saveQueue.Produce({.frameID=data.frameID,.size=data.size,.data=newdata,.additional=data.additional});
}

RecordFile::~RecordFile()
{
  saveQueue.Finish();
  if(workthread.joinable())
  {
    workthread.request_stop();
    workthread.join();
  }
}

long RecordFile::GetFileSaveTime()
{
  return FileSaveTime;
}

long RecordFile::GetQueueSize()
{
  return queueSize;
}

bool RecordFile::Status()
{
  return workthread.joinable();
}
